feat: four-point hook SPI (incoming, pre-storage, post-commit, outgoing) - #52
Merged
Merged
Conversation
Add pkg/hooks with a small Registry so callers can extend the server without forking. HTTP runs incoming after routing and outgoing before a resource envelope is written. Core runs pre-storage before persist and post-commit after commit (post-commit errors do not fail the write). Wire the same registry through runtime.Builder.WithHooks. Co-authored-by: Adegoke Adewoye <[email protected]>
Patch no longer delegates to Update, so pre-storage and post-commit see ActionPatch while persist stays VersionActionUpdate. Search and history bundles run outgoing hooks, transaction post-commit gets the real response bundle, update/patch pass Previous, and identity mutations after pre-storage are rejected. Co-authored-by: Adegoke Adewoye <[email protected]>
Keep the incoming Event.ResourceType on outgoing search/history so PHI hooks still see the queried type while Resource is the Bundle. Authorize HTTP PATCH as "patch" (SMART still maps to OpUpdate). Route /metadata through writeEnvelope so outgoing hooks can redact CapabilityStatement. Co-authored-by: Adegoke Adewoye <[email protected]>
POST /fhir incoming and outgoing hooks used ActionTransaction for batch bundles because routing cannot see Bundle.type. Parse the body first, then fire incoming/outgoing as batch. Core ProcessBatchBundle now runs post-commit with the response Bundle. Co-authored-by: Adegoke Adewoye <[email protected]>
degoke
marked this pull request as ready for review
September 21, 2026 11:37
Keep hook SPI write/batch paths and take FHIR Patch plus HTTP core imports from #50. PatchIfMatch still goes through patchAndCommit so ActionPatch and pre-storage stay on the If-Match path. Co-authored-by: Adegoke Adewoye <[email protected]>
Route $everything through writeBundleJSON like search and history so an outgoing hook can inspect or redact the compartment searchset. Co-authored-by: Adegoke Adewoye <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Item 3 of the HAPI-inspired build list: a small hook SPI so people can extend HAIStack without forking. Four pointcuts only — not HAPI’s interceptor bus.
Merged
mainafter #50 (REST table stakes). Conflicts were all overlapping edits, not competing intent: HTTP keeps bothpkg/coreandpkg/hooksimports; Patch/If-Match still go throughpatchAndCommitsoActionPatchstays, and the apply step usesapplyPatchDocumentfor FHIR Patch.Points
POST /fhir)$everythingbundle is serializedRegister with
hooks.NewRegistry().On(point, fn)and pass the same registry to core and HTTP viaruntime.Builder.WithHooks.Unknown points are rejected at registration. Hooks run in order; the first error stops the chain.
Review follow-ups
ActionPatch(persist is still an update)$everythinguseswriteBundleJSONso outgoing hooks see the compartment searchset (ActionOperation, query typePatient, envelopeBundle)Previousid/resourceTypeResourceTypeis the queried type (envelope remains Bundle)"patch"/metadataruns outgoingPOST /fhirusesActionBatchfor incoming, outgoing, and post-commit (notActionTransaction)Tests
pkg/hookspkg/corepkg/http$everythingbundle